﻿<template>
    <div class="main">
        <div class="editor">
            <Editor
                v-model="content"
                :defaultConfig="editorConfig"
                :mode="mode"
                @onCreated="editorHandleCreated"
                @onChange="onChange"
            />
        </div>
        <!-- <van-button class="button" @click="insertImg1">插入图片</van-button> -->
        <!-- <van-button class="button" @click="insertFile1">插入文件</van-button> -->
        <!-- <van-button class="button" @click="insertOl">插入列表</van-button> -->
        <!-- <van-button class="button" @click="getFileCount(1)">插入列表</van-button>-->
        <!-- <van-button class="button" @click="submit">submit</van-button> -->

        <Toolbar
            style="border-bottom: 1px solid #ccc"
            :editor="editorRef"
            class="toolbar"
            :defaultConfig="toolbarConfig"
            :mode="mode"
        />
    </div>
</template>

<script setup lang="ts">
import { ref, shallowRef, onUnmounted, onMounted } from 'vue';
// @ts-ignore
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import { debounce, getFileTypeIcon, getStore, loadImageWithRedirectSupportAndRetry, warningTips } from '@/utils/utils';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
import api from '@/apis/gounp';
import { h } from 'snabbdom';
import { Boot } from '@wangeditor/editor';
const config = ref<any>({});
const route = useRoute();
const content = ref('');
const editorRef = shallowRef();
const mode = ref('default');
const boldButton = ref<any>(null);
const olButton = ref<any>(null);
const ulButton = ref<any>(null);
const isSubmit = ref(false);
const isTopNotice = ref<string | null>('0'); //isTop 0 不置顶  1 置顶
const groupId = ref<string>(''); // 群id
const groupAnnouncementId = ref<string>(''); //群公告Id
const toolbarConfig = ref<any>({});
const editorConfig = {
    placeholder: t('PleaseEnterContent'),
    hoverbarKeys: {
        link: {
            menuKeys: [],
        },
        image: {
            menuKeys: [],
        },
        text: {
            menuKeys: [],
        },
    },
    sourceCode: false,
    maxLength: 600,
};

const renderAttachment = (elem: any, children: any, editor: any) => {
    const { fileName = '', link = '', href = '', alt = '', src = '' } = elem;
    const iconVnode = h('img', {
        className: 'attachment-icon',
        props: { src: src },
        style: { width: '22px', marginRight: '0.1em' },
    });
    const attachNameVnode = h(
        'span',
        {
            className: 'attachment-name',
            props: { contentEditable: false },
            style: { display: 'inline-block' },
        },
        [fileName]
    );
    const attachVnode = h(
        'div',
        {
            className: 'attachment-box',
            props: { contentEditable: false },
            style: { display: 'inline-block', marginLeft: '3px' },
            on: {
                click() {
                    console.log('clicked', link);
                },
            },
        },
        [iconVnode, attachNameVnode]
    );

    return attachVnode;
};

const renderElemConf = {
    type: 'attachment',
    renderElem: renderAttachment,
};

const attachmentToHtml = (elem: any, childrenHtml: any) => {
    // 获取附件元素的数据
    const { link = '', fileName = '', href = '', alt = '', src = '' } = elem;
    // 生成 HTML 代码
    const html = `<div
        data-w-e-type="attachment"
        data-w-e-is-inline
        data-link="${link}"
        data-fileName="${fileName}"
        data-href="${href}"
        data-alt="${alt}"
        alt="${alt}"
        src="${src}"
        class="attachment-box"
        title="${fileName}"
        >
        <img src="${src}" alt="${alt}" style="max-width: 100%; height: auto;"/><span class="attachment-name" data-alt="${alt}">${fileName}<span></div>`;

    return html;
};

const elemToHtmlConf = {
    type: 'attachment', // 新元素的 type ，重要！！！
    elemToHtml: attachmentToHtml,
};

const parseAttachmentHtml = (domElem: any, children: any, editor: any) => {
    const link = domElem.getAttribute('data-link') || '';
    const fileName = domElem.getAttribute('data-fileName') || '';
    const href = domElem.getAttribute('data-href') || '';
    const alt = domElem.getAttribute('data-alt') || '';
    const src = domElem.getAttribute('src') || '';

    const myResume = {
        type: 'attachment',
        link,
        fileName,
        href,
        alt,
        src,
        children: [{ text: '' }], // void node 必须有 children ，其中有一个空字符串，重要！！！
    };

    return myResume;
};

const parseHtmlConf = {
    selector: 'div[data-w-e-type="attachment"]', // CSS 选择器，匹配特定的 HTML 标签
    parseElemHtml: parseAttachmentHtml,
};

Boot.registerRenderElem(renderElemConf);
Boot.registerElemToHtml(elemToHtmlConf);
Boot.registerParseElemHtml(parseHtmlConf);

const submit = async () => {
    try {
        let isEmpty = editorRef.value.isEmpty();

        if (isEmpty) return warningTips(t('PleaseEnterContent'));

        if (isSubmit.value) return;
        isSubmit.value = true;
        // 0 文本  1 图片 2 文件 4 视频
        let announcement = editorRef.value.getHtml().replaceAll(config.value.imDomainUrl, '');
        // console.log(announcement, 'announcement');

        let children = editorRef.value.children;
        // console.log(children, 'children');

        let texts = [];
        let files = [];
        let images = [];
        let sorted = [];
        let olIndex = 1;
        for (const child of children) {
            if (child.type === 'attachment') {
                let fileObj = JSON.parse(child.alt.replace('file_', '').replaceAll("'", '"'));
                files.push({
                    fileName: fileObj.fileName,
                    fileSize: fileObj.fileSize,
                    url: fileObj.url,
                });
                sorted.push(2);
            }
            for (const item of child.children) {
                if (item.type === 'image') {
                    if (item.alt.startsWith('image')) {
                        let imgObj = JSON.parse(item.alt.split('image_')[1].replaceAll("'", '"'));
                        images.push({
                            height: imgObj.imgHeight,
                            width: imgObj.imgWidth,
                            url: imgObj.url,
                            thumbUrl: imgObj.thumbUrl,
                            size: imgObj.imgSize,
                        });
                        sorted.push(1);
                    } else if (item.alt.startsWith('file')) {
                        let fileObj = JSON.parse(item.alt.split('file_')[1].replaceAll("'", '"'));
                        files.push({
                            fileName: fileObj.fileName,
                            fileSize: fileObj.fileSize,
                            url: fileObj.url,
                        });
                        sorted.push(2);
                    }
                } else if (item.type === 'link') {
                    texts.push(item.url);
                    sorted.push(0);
                } else if (item.type === 'code') {
                    item.children.forEach((codeItem: any) => {
                        texts.push(codeItem.text);
                        sorted.push(0);
                    });
                } else if (!!item.text) {
                    let text = item.text;
                    if (child.type === 'list-item') {
                        if (child.ordered) {
                            text = `${olIndex++}. ${text}`;
                        }
                    } else {
                        olIndex = 1;
                    }
                    texts.push(text);
                    sorted.push(0);
                }
            }
        }

        // console.log(
        //     {
        //         texts,
        //         files,
        //         images,
        //         sorted,
        //     },
        //     'announcementMessage'
        // );

        api.updateGroupAnnouncement(groupId.value, {
            announcement,
            announcementMessage: JSON.stringify({
                texts,
                files,
                images,
                sorted,
            }),
            groupAnnouncementId: groupAnnouncementId.value,
            isTop: isTopNotice.value || '0',
        })
            .then(res => {
                isSubmit.value = false;
                if (!res || res.code != 1) return;

                _bridge.callNative('callAppRefreshGroupNoticeList', {
                    groupAnnouncementId: groupAnnouncementId.value,
                });

                _bridge.callNative('hideAppButton');
                goBack();
            })
            .catch(e => {
                console.log(e);
                isSubmit.value = false;
            });
    } catch (e) {
        console.log(e);
        isSubmit.value = false;
    }
};

const goBack = async () => {
    await _bridge.callNative('goBack');
};

const editorHandleCreated = (editor: any) => {
    // console.log('create');

    editorRef.value = editor;
    setTimeout(() => {
        boldButton.value = document.querySelector('[data-menu-key="bold"]'); //加粗
        olButton.value = document.querySelector('[data-menu-key="numberedList"]'); //有序
        setWindowFunction();
    });
};

const insertImg = async (jsonData: any) => {
    let dtoval: any = null;
    if (typeof jsonData === 'string') {
        dtoval = JSON.parse(jsonData);
    } else {
        dtoval = jsonData;
    }

    const { thumbPath, path, imgWidth, imgHeight, imgSize } = dtoval;
    const url = await loadImageWithRedirectSupportAndRetry(config.value.imDomainUrl + thumbPath);
    console.log(url, '----');

    let imgStr = `<img src="${url}" alt="image_${JSON.stringify({
        imgWidth,
        imgHeight,
        imgSize,
        url: path,
        thumbUrl: thumbPath,
    }).replace(new RegExp('"', 'g'), "'")}" data-href="${path}" />`;

    editorRef.value.dangerouslyInsertHtml(imgStr);
};

const insertFile = (jsonData: any) => {
    let dtoval: any = null;
    if (typeof jsonData === 'string') {
        dtoval = JSON.parse(jsonData);
    } else {
        dtoval = jsonData;
    }

    const { showImg, filePath, fileName, fileSize } = dtoval;
    const newShowImg = getFileTypeIcon(filePath);

    const customNode = {
        type: 'attachment',
        fileName: fileName,
        src: newShowImg,
        link: `${filePath}`,
        href: `${filePath}`,
        alt: `file_${JSON.stringify({ fileName: fileName, fileSize: fileSize, url: filePath }).replace(/"/g, "'")}`,
        children: [{ text: '' }],
    };
    editorRef.value.insertNode(customNode);
    const emptyNode = {
        type: 'paragraph',
        children: [{ text: '' }],
    };
    editorRef.value.insertNode(emptyNode);
};

const setWindowFunction = () => {
    window.groupNoticeSetBold = setBold;
    window.groupNoticeSetOl = setOl;
    window.insertImgToGroupNotice = insertImg;
    window.insertFileToGroupNotice = insertFile;
    window.getGroupNoticeFileCount = getFileCount;
};

// 1 图片  2 文件
const getFileCount = (type: number) => {
    if (type === 1) {
        return editorRef.value.getElemsByType('image').filter((i: any) => i.alt.startsWith('image')).length;
    } else if (type === 2) {
        return editorRef.value.getElemsByType('image').filter((i: any) => i.alt.startsWith('file')).length;
    }
    return editorRef.value.getElemsByType('image').length;
};

const setBold = () => {
    if (boldButton.value) {
        boldButton.value.click();
        getBoldButtonActiveDebounce();
    }
};

const setUl = () => {
    if (ulButton.value) {
        ulButton.value.click();

        // getULButtonActiveDebounce();
    }
};

const setOl = () => {
    if (olButton.value) {
        olButton.value.click();
        getOLButtonActiveDebounce();
    }
};

const insertImg1 = () => {
    insertImg({
        imgHeight: 600,
        imgSize: 410928,
        imgWidth: 277,
        path: '2025/11/13/52928a31b60b4f90a29187258a567813/5317a11d3d9a4c9cb57dd0919326bfcd.jpeg',
        thumbPath: '2025/11/13/52928a31b60b4f90a29187258a567813/thumbnail/5317a11d3d9a4c9cb57dd0919326bfcd.jpeg',
    });
};

const insertFile1 = () => {
    insertFile({
        showImg: 'im%2Fcn%2F6242edbc4d071005332efe27%2Ffiles%2F2025%2F11%2F11%2F41c66649e5c74161a013a9b933a47fc4.png',
        fileName: '《闪婚后发现老公是首富》.mp3',
        fileSize: 4331928,
        filePath: 'im/cn/6242edbc4d071005332efe27/files/2025/11/11/985b988642d24dbdab9b7d9f3bb1184f.mp3',
    });
};

const insertOl = () => {
    editorRef.value.dangerouslyInsertHtml('<ol><li>1</li><li>2</li><li>3</li></ol>');
};

const getBoldButtonActive = () => {
    setTimeout(() => {
        _bridge.callNative('setGroupNoticeButtonStatus', {
            key: 'bold',
            status: boldButton.value.classList.contains('active'),
        });
    }, 300);
};

const getOLButtonActive = () => {
    setTimeout(() => {
        _bridge.callNative('setGroupNoticeButtonStatus', {
            key: 'ol',
            status: olButton.value.classList.contains('active'),
        });
    }, 300);
};

const getData = (dataStr: string) => {
    if (!dataStr) return;
    dataStr = dataStr.replace(/<img(.*?)src="(.*?)"(.*?)>/g, (match, p1, p2, p3) => {
        if (p2.startsWith('http')) {
            return `<img${p1}src="${p2}"${p3}>`;
        }
        return `<img${p1}src="${config.value.imDomainUrl}${p2}"${p3}>`;
    });

    editorRef.value.setHtml(dataStr);
};

const getBoldButtonActiveDebounce = debounce(getBoldButtonActive, 500);
const getOLButtonActiveDebounce = debounce(getOLButtonActive, 500);

const onChange = () => {
    // console.log('change');
    getBoldButtonActiveDebounce();
    getOLButtonActiveDebounce();
};

onUnmounted(() => {
    window.getIsGroupNoticeInput = () => {
        return false;
    };
});

const getNotice = async () => {
    if (groupAnnouncementId.value === '0') return;
    const relsut = await api.getGroupAnnouncementDetail(groupId.value, groupAnnouncementId.value);

    if (!relsut || relsut.code !== 1 || !relsut.data.announcement) return;
    getData(relsut.data.announcement);
};

const created = async () => {
    config.value = getStore('mamak-config');
    // console.log(config.value, '--h5--');

    // 唤起键盘
    window.getIsGroupNoticeInput = () => {
        return true;
    };
    _bridge.callNative('setNavRightBtn', { type: 1, name: t('Publish') });
    _bridge.callNative('setTitle', { name: t('GroupNotice') });
    // 是否置顶
    window.setNoticeIsTop = ({ isTop }: any) => {
        isTopNotice.value = isTop;
    };

    window.rightBtnClick = submit;
    console.log('提交方法', 'rightBtnClick');
    // console.log(route.query, 'route.query');
    groupId.value = route.query.groupId as string;
    groupAnnouncementId.value = (route.query.groupAnnouncementId as string) || '0';

    getNotice();
};

created();
</script>

<style scoped lang="scss">
.main {
    width: 100vw;
    height: 100%;
    text-align: left;
    background: #ffffff;
    box-sizing: border-box;

    .editor {
        height: calc(100% - 50px);
        overflow-y: auto;
        padding: 10px;

        :deep(.w-e-text-container) {
            min-height: 400px;
            background: #f5f5f5;
            border-radius: 4px;

            .w-e-text-placeholder {
                top: 9px;
            }

            .w-e-scroll {
                min-height: 400px;
                overflow-y: auto;
                padding-bottom: 12px;
                &::-webkit-scrollbar {
                    width: 0;
                    display: none;
                }

                div:first-child {
                    p:first-child {
                        margin-top: 8px;
                    }
                }

                > div {
                    min-height: 400px;
                }
            }

            img {
                min-height: unset;
                min-width: unset;
            }

            .w-e-selected-image-container {
                overflow: unset;
            }
        }
    }

    .toolbar {
        position: fixed;
        top: -900px;
    }

    :deep(p) {
        margin: 0;
    }

    :deep(div) {
        margin: 0 !important;
    }

    :deep(a) {
        color: #3381f1;
    }
}

:deep(.attachment-box) {
    display: flex !important;
    align-items: center;
}
</style>

<style>
body {
    min-height: unset;
}

.attachment-name {
    white-space: nowrap;
    /* 防止文本换行 */
    overflow: hidden;
    /* 隐藏 溢出 内容 */
    text-overflow: ellipsis;
}
</style>
